#include "editor.h"
#include "document.h"
#include "item/item.h"
#include "view/view.h"
#include "view/scene.h"
#include "OldGraphicsView/Palette.h"
#include "OldGraphicsView/PaletteLoader.h"
#include "OldGraphicsView/Settings.h"
#include "command/command.h"
#include "toolmanager.h"
#include "snapmanager.h"

#include "dock/taskdockwidget.h"
#include "dock/undodockwidget.h"

#include "core/core.h"

#include <QMainWindow>
#include <QAction>
#include <QToolBar>
#include <QUndoStack>

#include <QFileInfo>
#include <QTimer>

namespace SymbolEditor
{

    Editor::Editor(QObject *parent) :
        IEditor(parent),
        m_scene(new Scene(this)),
        m_view(new View()),
        m_undoStack(new QUndoStack(this))
    {
        setWidget(m_view);

        addDockWidgets();
        addSnapTools();
        addInteractiveTools();
    }

    Editor::~Editor()
    {
        removeInteractiveTools();
        removeSnapTools();
        removeDockWidets();
    }

    void Editor::pushCommand(UndoCommand *command)
    {
        command->setDocument(m_document);
        m_undoStack->push(command);
    }

    void Editor::addDocumentItem(quint64 id, const Item *item)
    {
        m_scene->addDocumentItem(id, item);
        //m_selectTool->addDocumentItem(id, item);
    }

    void Editor::updateDocumentItemProperty(quint64 itemId, quint64 propertyId, const QVariant &value)
    {
        m_scene->updateDocumentItemProperty(itemId, propertyId, value);
        //m_selectTool->updateDocumentItemProperty(itemId, propertyId, value);
    }

    void Editor::removeDocumentItem(quint64 id)
    {
        m_scene->removeDocumentItem(id);
        //m_selectTool->removeDocumentItem(id);
    }

    void Editor::updateDocumentItemStack(quint64 itemId, quint64 beforeId)
    {
        auto item = m_scene->itemForDocumentId(itemId);
        auto before = m_scene->itemForDocumentId(beforeId);
        item->stackBefore(before);
        m_scene->update();
    }

    void Editor::applySettings(const LeGraphicsView::Settings &settings)
    {
        m_scene->applySettings(settings);
        m_view->applySettings(settings);
        m_interactiveToolManager->applySettings(settings);
        m_snapToolManager->applySettings(settings);
        m_undoDockWidget->applySettings(settings);
        m_taskDockWidget->applySettings(settings);

        // FIXME
        LeGraphicsView::PaletteLoader paletteLoader;
        paletteLoader.setPath(Core::dataPath("/settings/symboleditor"));
        paletteLoader.loadPalettes();
        LeGraphicsView::Palette palette = paletteLoader.palette(settings.paletteName);
        m_view->setPalette(palette);
        m_scene->setPalette(palette);
    }

    // TODO:
    //  - cleanupEditor(); // disconnect, setScene(nullptr), remove event filters, ...
    //  - loadDocument();
    //  - setupEditor(); // connect, setScene, installEventFiler, ...
    // Or just load document, and setup/cleanup in activate/desactivate
    bool Editor::open(QString *errorString, const QString &fileName)
    {
        m_document = new Document();
        m_document->setFilePath(fileName);
        QFileInfo fileInfo(fileName);
        m_document->setDisplayName(fileInfo.baseName());

        bool result = m_document->load(errorString, m_document->filePath());
        if (!result)
        {
            return false;
        }

        for (quint64 id : m_document->itemIdList())
        {
            addDocumentItem(id, m_document->item(id));
        }

        connect(m_document, &Document::itemAdded,
                this, &Editor::addDocumentItem);
        connect(m_document, &Document::itemPropertyChanged,
                this, &Editor::updateDocumentItemProperty);
        connect(m_document, &Document::itemRemoved,
                this, &Editor::removeDocumentItem);
        connect(m_document, &Document::itemStackReordered,
                this, &Editor::updateDocumentItemStack);

        m_scene->setSceneRect(0, 0, 297, 210); // FIXME

        m_undoDockWidget->setStack(m_undoStack);

        // FIXME: separate setScene from installEventFilter?
        // Last event handler executed first
        m_interactiveToolManager->setScene(m_scene);
        m_view->setScene(m_scene);
        m_snapToolManager->setScene(m_scene);
        m_snapToolManager->setView(m_view);

        m_view->fitInView(m_scene->sceneRect(), Qt::KeepAspectRatio);

        return true;
    }

    IDocument *Editor::document() const
    {
        return m_document;
    }

    QIcon Editor::icon() const
    {
        return QIcon(":/icons/sch.png");
    }

    QString Editor::displayName() const
    {
        return m_document->displayName();
    }

    void Editor::activate(QMainWindow *win)
    {
        win->addToolBar(m_interactiveToolBar);
        m_interactiveToolBar->show();

        win->addToolBar(m_snapToolBar);
        m_snapToolBar->show();

        win->addDockWidget(Qt::RightDockWidgetArea, m_taskDockWidget);
        m_taskDockWidget->show();

        win->addDockWidget(Qt::RightDockWidgetArea, m_undoDockWidget);
        m_undoDockWidget->show();
        win->tabifyDockWidget(m_taskDockWidget, m_undoDockWidget);
    }

    void Editor::desactivate(QMainWindow *win)
    {
        win->removeDockWidget(m_undoDockWidget);
        win->removeDockWidget(m_taskDockWidget);
        win->removeToolBar(m_snapToolBar);
        win->removeToolBar(m_interactiveToolBar);
    }

    void Editor::addInteractiveTools()
    {
        m_interactiveToolManager = new ToolManager(this);
        connect(m_interactiveToolManager, &ToolManager::taskWidgetsChanged,
                m_taskDockWidget, &TaskDockWidget::setTaskWidgets);
        connect(m_interactiveToolManager, &ToolManager::newCommandAvailable,
                this, [this]()
        {
            auto command = m_interactiveToolManager->nextPendingCommand();
            command->setDocument(m_document);
            m_undoStack->push(command);
        });

        m_interactiveToolBar = new QToolBar();
        m_interactiveToolBar->addActions(m_interactiveToolManager->actions());
    }

    void Editor::removeInteractiveTools()
    {

    }

    void Editor::addSnapTools()
    {
        m_snapToolManager = new SnapManager(this);
        m_snapToolBar = new QToolBar();
        m_snapToolBar->addActions(m_snapToolManager->actions());
    }

    void Editor::removeSnapTools()
    {

    }

    void Editor::addDockWidgets()
    {
        // Task dockwidget non-movable and no dock decoration
        m_taskDockWidget = new TaskDockWidget();
        m_taskDockWidget->setAllowedAreas(Qt::RightDockWidgetArea);
        m_taskDockWidget->setFeatures(0);
        m_taskDockWidget->setTitleBarWidget(new QWidget());

        // Undo dockwidget movable with default decoration (could be a navigation widget?)
        m_undoDockWidget = new UndoDockWidget();
    }

    void Editor::removeDockWidets()
    {

    }

}
